package com.tsing.wms.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tsing.wms.config.RedisManager;
import com.tsing.wms.constant.AuthConsts;
import com.tsing.wms.entity.OutInRecordEntity;
import com.tsing.wms.entity.StockEntity;
import com.tsing.wms.entity.StorehouseEntity;
import com.tsing.wms.entity.UserEntity;
import com.tsing.wms.exception.CommonException;
import com.tsing.wms.exception.ServerException;
import com.tsing.wms.mapper.OutInRecordMapper;
import com.tsing.wms.mapper.StockMapper;
import com.tsing.wms.mapper.StorehouseMapper;
import com.tsing.wms.mapper.UserMapper;
import com.tsing.wms.service.IStorehouseService;
import com.tsing.wms.util.GetLoginUserUtil;
import com.tsing.wms.vo.PageResultVO;
import com.tsing.wms.vo.req.IdReqVO;
import com.tsing.wms.vo.req.IdsReqVO;
import com.tsing.wms.vo.req.StoreReqVO;
import com.tsing.wms.vo.req.SupplierPageReqVO;
import com.tsing.wms.vo.resp.StoreRespVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;

/**
 * <p>
 * 仓库表 服务实现类
 * </p>
 *
 * @author TheTsing
 * @since 2022-04-13
 */
@Service
public class StorehouseServiceImpl extends ServiceImpl<StorehouseMapper, StorehouseEntity> implements IStorehouseService {

    @Autowired
    private RedisManager redisManager;

    @Override
    public void addStore(StoreReqVO reqVO, HttpServletRequest request) {
        if (GetLoginUserUtil.getLoginUserInfo(request.getHeader(AuthConsts.AUTHENTICATION_HEAD), redisManager).getIdentity() != 1) {
            throw new ServerException(CommonException.Proxy.AUTHORIZATION_EXCEPTION);
        }
        if (ObjectUtil.isNotNull(new LambdaQueryChainWrapper<>(baseMapper)
                .select(StorehouseEntity::getId)
                .eq(StorehouseEntity::getName, reqVO.getName())
                .one())) {
            throw new ServerException(CommonException.Proxy.STORE_IS_NOTNULL);
        }
        StorehouseEntity storehouseEntity = new StorehouseEntity();
        BeanUtil.copyProperties(reqVO, storehouseEntity);
        baseMapper.insert(storehouseEntity);
    }

    @Resource
    private StockMapper stockMapper;
    @Resource
    private OutInRecordMapper outInRecordMapper;

    @Override
    public void deleteStore(IdsReqVO reqVO, HttpServletRequest request) {
        if (GetLoginUserUtil.getLoginUserInfo(request.getHeader(AuthConsts.AUTHENTICATION_HEAD), redisManager).getIdentity() != 1) {
            throw new ServerException(CommonException.Proxy.AUTHORIZATION_EXCEPTION);
        }
        if (0 != new LambdaQueryChainWrapper<>(stockMapper)
                .select(StockEntity::getId)
                .in(StockEntity::getStorehouseId, reqVO.getIds())
                .count()) {
            throw new ServerException(CommonException.Proxy.STORE_RELEVANCE_STOCK);
        }
        if (0 != new LambdaQueryChainWrapper<>(outInRecordMapper)
                .select(OutInRecordEntity::getId)
                .in(OutInRecordEntity::getStorehouseId, reqVO.getIds())
                .count()) {
            throw new ServerException(CommonException.Proxy.STORE_RELEVANCE_RECORD);
        }
        baseMapper.deleteBatchIds(reqVO.getIds());
    }

    @Resource
    private UserMapper userMapper;

    @Override
    public StoreRespVO getStore(IdReqVO reqVO) {
        StorehouseEntity storehouseEntity = baseMapper.selectById(reqVO.getId());
        StoreRespVO storeRespVO = new StoreRespVO();
        BeanUtil.copyProperties(storehouseEntity, storeRespVO);
        storeRespVO.setUsername(new LambdaQueryChainWrapper<>(userMapper)
                .select(UserEntity::getUsername)
                .eq(UserEntity::getId, storeRespVO.getUserId())
                .one()
                .getUsername());
        return storeRespVO;
    }

    @Override
    public void updateStore(StoreReqVO reqVO, HttpServletRequest request) {
        if (GetLoginUserUtil.getLoginUserInfo(request.getHeader(AuthConsts.AUTHENTICATION_HEAD), redisManager).getIdentity() != 1) {
            throw new ServerException(CommonException.Proxy.AUTHORIZATION_EXCEPTION);
        }
        if (StrUtil.isNotBlank(reqVO.getName())) {
            if (ObjectUtil.isNotNull(new LambdaQueryChainWrapper<>(baseMapper)
                    .select(StorehouseEntity::getId)
                    .eq(StorehouseEntity::getName, reqVO.getName())
                    .ne(StorehouseEntity::getId, reqVO.getId())
                    .one())) {
                throw new ServerException(CommonException.Proxy.STORE_IS_NOTNULL);
            }
        }
        StorehouseEntity storehouseEntity = new StorehouseEntity();
        BeanUtil.copyProperties(reqVO, storehouseEntity);
        baseMapper.updateById(storehouseEntity);
    }

    @Override
    public PageResultVO<StoreRespVO> storePage(SupplierPageReqVO reqVO) {
        IPage<StorehouseEntity> page = new Page<>(reqVO.getPageNum(), reqVO.getPageSize());
        new LambdaQueryChainWrapper<>(baseMapper)
                .like(StrUtil.isNotBlank(reqVO.getName()), StorehouseEntity::getName, reqVO.getName())
                .page(page);
        List<StoreRespVO> storeRespVOs = BeanUtil.copyToList(page.getRecords(), StoreRespVO.class);
        storeRespVOs.forEach(item -> {
            UserEntity userEntity = new LambdaQueryChainWrapper<>(userMapper)
                    .select(UserEntity::getUsername, UserEntity::getPhone)
                    .eq(UserEntity::getId, item.getUserId())
                    .one();
            item.setUsername(userEntity.getUsername());
            item.setPhone(userEntity.getPhone());
            item.setGoodsTypeCount(new LambdaQueryChainWrapper<>(stockMapper)
                    .select(StockEntity::getId)
                    .eq(StockEntity::getStorehouseId, item.getId())
                    .count());
            item.setGoodsCount(baseMapper.selectGoodsCount(item.getId()));
        });
        return new PageResultVO<>(page, storeRespVOs);
    }

}
